#include "Monster.h"
#include<iostream>
#include"Character.h"
#include <cstdlib>
#include "Methods.h"
#include "Effect.h"
Monster::Monster(std::string name, std::string info, int h, int at, int de, int m)
    : monsterName(name), monsterInfo(info), currentHealth(h),
    maxHealth(h), attack(at), defense(de), methods(m) {
    m_ = new Methods();
    m_->addEffect(std::make_shared<AttackBoostEffect>(1.0f, 3));
    m_->addEffect(std::make_shared<DefenseBoostEffect>(1.0f, 3));
    m_->addEffect(std::make_shared<HealEffect>(1.0f, 20));
    m_->addEffect(std::make_shared<StunEffect>(0.3f, 1));
}
Monster::~Monster() {
    delete m_;  // 释放
}
void Monster::OnTakeDamage(int value) {
    int final = value - defense;
    if (final < 1) final = 1;

    currentHealth -= final;
    if (currentHealth < 0) currentHealth = 0;

    std::cout << monsterName << "受到了 " << final << " 点伤害！\n";
    std::cout << "当前生命值: " << currentHealth << "/" << maxHealth << "\n";

    if (currentHealth <= 0) {
        std::cout << ">> " << monsterName << "已被击败！ <<\n";
    }
}

void Monster::Attack(Character& character)
{
    std::cout << "怪物攻击了玩家" << std::endl;
    AttackEffect(methods,character);
}

void Monster::AttackEffect(int methods, Character& character)
{
    switch (methods)
    {
    case 0:
        std::cout << "无特殊效果" << std::endl;
        break;
    case 1:
        m_->applyEffectById(0, character);
        
        break;
    case 2:
        m_->applyEffectById(1, character);
        break;
    case 3:
        
        m_->applyEffectById(2, character);
        break;
    case 4:
        
        m_->applyEffectById(3, character);
        
        break;
    default:
        std::cout << "默认效果" << std::endl;
    }
}

#pragma region"属性及状态获取"
bool Monster::isAlive() const {
    return currentHealth > 0;
}

std::string Monster::getName() const {
    return monsterName;
}

std::string Monster::getInfo() const {
    return monsterInfo;
}

int Monster::getDefense() const {
    return defense;
}

int Monster::getCurrentHealth() const {
    return currentHealth;
}

int Monster::getMaxHealth() const {
    return maxHealth;
}

int Monster::getAttack() const {
    return attack;
}

int Monster::getMethods() const
{
    return methods;
}
#pragma endregion

#pragma region"修改属性"
void Monster::setMaxHealth(int h)
{
    maxHealth = h;
}

void Monster::setCurrentHealth(int h)
{
    currentHealth = h;
}

void Monster::setAttack(int a)
{
    attack = a;
}

void Monster::setDefense(int d)
{
    defense = d;
}
#pragma endregion

Monster::Monster(const Monster& other)
    : monsterName(other.monsterName)
    , monsterInfo(other.monsterInfo)
    , currentHealth(other.currentHealth)
    , maxHealth(other.maxHealth)
    , attack(other.attack)
    , defense(other.defense)
    , methods(other.methods)
    , m_(new Methods(*other.m_))   // 用 Methods 的拷贝构造
{}

//深拷贝
Monster& Monster::operator=(const Monster& other) {
    if (this != &other) {
        delete m_;
        monsterName = other.monsterName;
        monsterInfo = other.monsterInfo;
        currentHealth = other.currentHealth;
        maxHealth = other.maxHealth;
        attack = other.attack;
        defense = other.defense;
        methods = other.methods;
        m_ = new Methods(*other.m_);
    }
    return *this;
}

//移动构造
Monster::Monster(Monster&& other) noexcept
    : monsterName(std::move(other.monsterName))
    , monsterInfo(std::move(other.monsterInfo))
    , currentHealth(other.currentHealth)
    , maxHealth(other.maxHealth)
    , attack(other.attack)
    , defense(other.defense)
    , methods(other.methods)
    , m_(other.m_)
{
    other.m_ = nullptr;
}

//移动赋值
Monster& Monster::operator=(Monster&& other) noexcept {
    if (this != &other) {
        delete m_;
        monsterName = std::move(other.monsterName);
        monsterInfo = std::move(other.monsterInfo);
        currentHealth = other.currentHealth;
        maxHealth = other.maxHealth;
        attack = other.attack;
        defense = other.defense;
        methods = other.methods;
        m_ = other.m_;
        other.m_ = nullptr;
    }
    return *this;
}